using System;
using System.Threading;

namespace Pinwheel.Toolkits.DigestGenerator
{
    public struct Guid
    {
        private long _guid;
        public Guid(long value)
        {
            _guid = value;
        }
        
        // 重写 Equals 方法
        public override bool Equals(object obj)
        {
            if (!(obj is Guid))
                return false;

            Guid other = (Guid)obj;
            return this._guid == other._guid;
        }
        
        // 重写 GetHashCode 方法
        public override int GetHashCode()
        {
            return _guid.GetHashCode();
        }
        
        // 重写 ToString 方法
        public override string ToString()
        {
            return $"Guid: {_guid}";
        }
        #region Operator

        // 重写 == 运算符
        public static bool operator ==(Guid g1, Guid g2)
        {

            return g1._guid == g2._guid;
        }
        
        // 重写 != 运算符
        public static bool operator !=(Guid g1, Guid g2)
        {
            return g1._guid != g2._guid;
        }
        #endregion
        
        
        public static implicit operator Guid(long value)
        {
            return new Guid(value);
        }
        
        public static implicit operator long(Guid guid)
        {
            return guid._guid;
        }
    }
    
    public static class GuidGenerator
    {
        internal const byte TOTAL_BIT = 64;
        internal const byte STAMP_BIT = 42;
        internal const byte INT_BIT = TOTAL_BIT - STAMP_BIT;
        internal const int MAX_ID = (1 << INT_BIT) - 1;
        
        private static int _curId = 0;
        
        public static long Long()
        {
            return Guid();
        }
        
        public static Guid Guid()
        {
            var stamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            // var stamp = DateTimeOffset.UtcNow.Ticks;
            // Debug.Log($"stamp->{stamp << INT_BIT}");
            if (_curId > MAX_ID) Interlocked.CompareExchange(ref _curId, 0, MAX_ID);
            long id = Interlocked.Increment(ref _curId);
            return new Guid((stamp << INT_BIT) | id);
        }
    }
}